package com.jeff.utils;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.hardware.SensorManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationManager;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.support.annotation.RequiresPermission;
import android.telephony.TelephonyManager;
import android.text.TextUtils;

import com.jeff.utils.security.TEAUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.util.Hashtable;

import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;

/**
 * author：duff
 * version：1.0.0
 * date：2017/9/1
 */
public class DeviceUtil {
    private static int LENGTH_DEVICE_ID = 23;
    private static final String PERSIST_RADIO_IMEI = "persist.radio.imei";
    private static final String RO_RIL_OEM_IMEI = "ro.ril.oem.imei";
    private static final String OEM_DEVICE_IMEI_CACHE = "oem.device.imeicache";
    public static final String GET_PROP_COMMAND = "getprop %s";


    /**
     * @param context
     * @return version name
     */
    public static String getVersionName(Context context) {
        PackageManager manager = context.getPackageManager();
        try {
            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
            return info.versionName;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "0.0.0";
    }

    /**
     * @param context
     * @return version code
     */
    public static int getVersionCode(Context context) {
        PackageManager manager = context.getPackageManager();
        try {
            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
            return info.versionCode;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * @param context
     * @return App 基本信息集合
     */
    public static Hashtable getProjectBaseInfo(Context context) {
        Hashtable htable = new Hashtable();
        PackageManager manager = context.getPackageManager();
        try {
            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
            String packageName = info.packageName;
            int versionCode = info.versionCode;
            String versionName = info.versionName;
            htable.put("package_name", packageName);
            htable.put("version_code", versionCode);
            htable.put("version_name", versionName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return htable;
    }

    /**
     * IMSI共有15位，其结构如下：MCC+MNC+MSIN ，（MNC+MSIN=NMSI）
     * MCC：Mobile Country Code，移动国家码，MCC的资源由国际电联（ITU）统一分配和管理，唯一识别移动用户所属的国家，共3位，中国为460;<br/>
     * MNC:Mobile Network Code，移动网络码，共2位，中国移动TD系统使用00，中国联通GSM系统使用01，中国移动GSM系统使用02，中国电信CDMA系统使用03，一个典型的IMSI号码为460030912121001<br/>
     * MSIN:Mobile Subscriber Identification Number共有10位，其结构如下：09+M0M1M2M3+ABCD　其中的M0M1M2M3和MDN号码中的H0H1H2H3可存在对应关系，ABCD四位为自由分配。可以看出IMSI在MSIN号码前加了MCC即NMSI
     * ，可以区别出每个用户的来自的国家，因此可以实现国际漫游。在同一个国家内，如果有多个移动网络运营商，可以通过MNC来进行区别。<br/>
     *
     * @param context
     * @return
     */
    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
    public static String getIMSI(Context context) {
        String imsi = "";
        if (checkPermissions(context, Manifest.permission.READ_PHONE_STATE)) {
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            imsi = telephonyManager.getSubscriberId();
            if (imsi == null) {
                imsi = "";
            }
        }

        return imsi;
    }

    public static String getWifiMacAddress(Context context) {
        String macAddress = "";
        if (checkPermissions(context, Manifest.permission.ACCESS_WIFI_STATE)) {
            macAddress = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)).getConnectionInfo().getMacAddress();
            if (macAddress == null) {
                macAddress = "";
            }
        }

        return macAddress;
    }

    public static String getEncryptWifiMacAddress(Context context) {
        String macAddress = getWifiMacAddress(context);
        StringBuilder macAddressBuilder = new StringBuilder();
        for (int i = 0; i < macAddress.length(); i++) {
            char c = macAddress.charAt(i);
            if (!(c == '-' || c == ':')) {
                macAddressBuilder.append(c);
            }
        }

        return TEAUtil.encrypt(macAddressBuilder.toString());
    }

    /**
     * @return Android 系统版本
     */
    public static String getOSVersion() {
        return Build.VERSION.RELEASE;
    }

    /**
     * @return serial number
     */
    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
    public static String getSerial() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            return Build.getSerial();
        } else {
            return Build.SERIAL;
        }
    }

    /**
     * Get Phone's type
     *
     * @param
     * @return
     */
    public static String getPhoneType() {
        return Build.MODEL;
    }

    /**
     * Get Phone's SDK
     *
     * @return
     */
    public static String getSDK() {
        return NumberUtil.toString(Build.VERSION.SDK_INT);
    }

    /**
     * Get Phone's Release
     *
     * @return
     */
    public static String getRelease() {
        return Build.VERSION.RELEASE;
    }


    /**
     * Get Phone's OS version
     *
     * @return
     */
    public static String getOSVersionAndSDKVersion() {
        String version = getRelease() + "," + getSDK();
        return version;
    }

    public static String getDeviceName() {
        String manufacturer = Build.MANUFACTURER;
        String model = Build.MODEL;
        if (manufacturer != null && model != null) {
            if (model.startsWith(manufacturer)) {
                return model;
            } else {
                return manufacturer + " " + model;
            }
        }
        return "unknown";
    }

    /**
     * 移动国家码和移动网络码<br/>
     * IMSI共有15位，其结构如下：MCC+MNC+MSIN ，（MNC+MSIN=NMSI）
     * MCC：Mobile Country Code，移动国家码，MCC的资源由国际电联（ITU）统一分配和管理，唯一识别移动用户所属的国家，共3位，中国为460;<br/>
     * MNC:Mobile Network Code，移动网络码，共2位，中国移动TD系统使用00，中国联通GSM系统使用01，中国移动GSM系统使用02，中国电信CDMA系统使用03，一个典型的IMSI号码为460030912121001<br/>
     * MSIN:Mobile Subscriber Identification Number共有10位，其结构如下：09+M0M1M2M3+ABCD　其中的M0M1M2M3和MDN号码中的H0H1H2H3可存在对应关系，ABCD四位为自由分配。可以看出IMSI在MSIN号码前加了MCC即NMSI
     * ，可以区别出每个用户的来自的国家，因此可以实现国际漫游。在同一个国家内，如果有多个移动网络运营商，可以通过MNC来进行区别。<br/>
     *
     * @param context
     * @return
     */
    public static String getMCCMNC(Context context) {
        String mccmnc = "";
        if (checkPermissions(context, Manifest.permission.READ_PHONE_STATE)) {
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            mccmnc = telephonyManager.getSimOperator();
        }
        return mccmnc;
    }

    public static String getWifiMac(Context context) {
        String rt = "";
        if (context != null && checkPermissions(context, Manifest.permission.ACCESS_WIFI_STATE)) {
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            if (wifiManager == null || wifiManager.getConnectionInfo() == null) {
                return rt;
            }

            return wifiManager.getConnectionInfo().getMacAddress();
        }
        return rt;
    }

    @RequiresPermission(Manifest.permission.BLUETOOTH)
    public static String getBTMac(Context context) {
        String rt = "";
        if (context != null && checkPermissions(context, Manifest.permission.BLUETOOTH)) {
            BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
            if (btAdapter != null) {
                rt = btAdapter.getAddress();
            }
        }
        return rt;
    }

    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
    public static String getIMEI(Context context) {
        String rt = "";
        if (context != null && checkPermissions(context, Manifest.permission.READ_PHONE_STATE)) {
            TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            if (tm != null) {
                rt = tm.getDeviceId();
            }
        }
        if (TextUtils.isEmpty(rt)) {
            rt = getIMEIByExecuteCommand();
        }
        return rt;
    }

    public static boolean haveGPS(Context context) {
        boolean rt = false;
        if (context != null) {
            LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            rt = (locationManager != null);
        }
        return rt;
    }

    public static boolean haveBT(Context context) {
        boolean rt = false;
        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
        rt = (btAdapter != null);
        return rt;
    }

    public static boolean haveGravity(Context context) {
        boolean rt = false;
        if (context != null) {
            SensorManager manager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
            rt = (manager != null);
        }
        return rt;
    }

    public static boolean haveWifi(Context context) {
        boolean rt = false;
        if (context != null) {
            WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
            rt = (wifiManager != null);
        }
        return rt;
    }

    public static boolean isRooted() {
        boolean rt = false;
        String envPath = System.getenv("PATH");
        String[] array = envPath.split(":");
        for (int i = 0; i < array.length; i++) {
            String suPath = array[i] + File.separator + "su";
            File f = new File(suPath);
            if (f != null && f.exists()) {
                rt = f.canExecute();
                if (rt == true) {
                    break;
                }
            }
        }
        return rt;
    }

    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
    public static Location getLocation(Context context) {
        Location location = null;
        if (checkPermissions(context, Manifest.permission.ACCESS_FINE_LOCATION) || checkPermissions(context, Manifest.permission.ACCESS_COARSE_LOCATION)) {
            LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            if (locationManager != null) {
                Criteria criteria = new Criteria();
                criteria.setAccuracy(Criteria.ACCURACY_COARSE);
                criteria.setPowerRequirement(Criteria.POWER_LOW);
                criteria.setAltitudeRequired(false);
                criteria.setBearingRequired(false);
                criteria.setSpeedRequired(false);
                criteria.setCostAllowed(false);
                String provider = locationManager.getBestProvider(criteria, false);
                if (provider != null) {
                    location = locationManager.getLastKnownLocation(provider);
                }
            }
        }
        return location;
    }

    public static boolean checkPermissions(Context context, String permission) {
        PackageManager pm = context.getPackageManager();
        boolean rt = (pm.checkPermission(permission, context.getPackageName()) == PackageManager.PERMISSION_GRANTED);
        return rt;
    }

    public static String getPackageName(Context context) {
        String packageName = "";
        try {
            PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            packageName = info.packageName;
        } catch (PackageManager.NameNotFoundException e) {
        }
        return packageName;
    }


    private static String getIMEIByExecuteCommand() {

        String imei = getIMEIByExecuteCommand(PERSIST_RADIO_IMEI);

        if (TextUtils.isEmpty(imei)) {
            imei = getIMEIByExecuteCommand(RO_RIL_OEM_IMEI);
        }

        if (TextUtils.isEmpty(imei)) {
            imei = getIMEIByExecuteCommand(OEM_DEVICE_IMEI_CACHE);
        }
        return imei;
    }

    private static String getIMEIByExecuteCommand(String key) {
        Process process;
        BufferedReader bufferedReader = null;
        String imei = "";
        try {
            StringBuilder stringBuilder = new StringBuilder();
            process = Runtime.getRuntime().exec(String.format(GET_PROP_COMMAND, key));
            String line;
            bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            while ((line = bufferedReader.readLine()) != null) {
                stringBuilder.append(line).append('\n');
            }
            process.waitFor();
            imei = stringBuilder.toString().trim();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return imei;
    }

}
